package com.boarsoft.boar.message.flow;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.beans.factory.annotation.Autowired;

import com.boarsoft.boar.message.service.MsgServerService;
import com.boarsoft.common.dao.PagedResult;
import com.boarsoft.flow.core.bean.ProcessHandler;
import com.boarsoft.message.bean.MessageEntity;
import com.boarsoft.message.bean.TargetQueueInfo;
import com.boarsoft.rpc.bean.RpcReferenceConfig;
import com.boarsoft.rpc.bean.RpcRegistry;
import com.boarsoft.rpc.core.RpcContext;

public class MsgHandler implements ProcessHandler {

	@Autowired
	private RpcContext rpcContext;

	@Autowired
	private MsgServerService messageBrockerService;

	@Override
	@SuppressWarnings("unchecked")
	public Object process(String entry, Object data, Throwable throwable) throws Throwable {
		Map<String, Object> map = (Map<String, Object>) data;
		// 根据流程引擎的配置传参不同，调用不同的函数，这样避免写多个handler
		// 流程引擎的参数是传递性的，所以上一次执行的结果必须放进map
		switch (entry) {
		case MessageStr.ADDR:
			map.put(MessageStr.ADDR_LIST, getAddr());
			break;
		case MessageStr.QUEUE:
			map.put(MessageStr.QUEUE_LIST, getQueue((List<String>) map.get(MessageStr.ADDR_LIST)));
			break;
		case MessageStr.FILTER_QUEUE:
			Map<String, List<TargetQueueInfo>> queueList = (Map<String, List<TargetQueueInfo>>) map.get(MessageStr.QUEUE_LIST);
			map.put(MessageStr.QUEUE_LIST, filterQueue(queueList, map.get(MessageStr.TARGET).toString()));
			break;
		case MessageStr.MSG:
			map.put(MessageStr.MSG_LIST, msgList(map));
			break;
		default:
			break;
		}
		return map;
	}

	/**
	 * 获取中间件地址
	 * 
	 * @return
	 */
	private List<String> getAddr() {
		RpcRegistry reg = rpcContext.getMyRegistry();
		Map<String, RpcReferenceConfig> refMap = reg.getReferenceMap();
		RpcReferenceConfig rc = refMap.get("serverMsgSvc");
		List<RpcRegistry> aLt = rpcContext.getAllProvidersByKey(rc.getSign(), false);
		List<String> rLt = new ArrayList<String>();
		// 当没有活动的消息中心时，aLt可能为空
		if (aLt != null && !aLt.isEmpty()) {
			for (RpcRegistry rr : aLt) {
				rLt.add(rr.getKey());
			}
		}
		return rLt;
	}

	/**
	 * 获取队列
	 * 
	 * @param addrs
	 *            中间件地址
	 * @return
	 */
	private Map<String, List<TargetQueueInfo>> getQueue(List<String> addrs) {
		Map<String, List<TargetQueueInfo>> map = new HashMap<>();
		for (String addr : addrs) {
			List<TargetQueueInfo> queues = messageBrockerService.getQueueInfo(addr);
			map.put(addr, queues);
		}
		return map;
	}

	/**
	 * 根据用户传来的队列code来帅选出包含该队列的中间件
	 * 
	 * @param map
	 * @param queueCode
	 *            队列code
	 * @return
	 */
	private Map<String, TargetQueueInfo> filterQueue(Map<String, List<TargetQueueInfo>> map, String queueCode) {
		Map<String, TargetQueueInfo> res = new HashMap<>();
		for (Entry<String, List<TargetQueueInfo>> entry : map.entrySet()) {
			List<TargetQueueInfo> queues = entry.getValue();
			for (TargetQueueInfo targetQueueInfo : queues) {
				if (targetQueueInfo.getCode().equals(queueCode)) {
					res.put(entry.getKey(), targetQueueInfo);
					break;
				}
			}
		}
		return res;
	}

	/**
	 * 查询帅选后的队列列表包含的消息列表，每个队列最多获取50条， 然后进行聚合，最后根据addTime进行降序排序
	 * 
	 * @param map
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private PagedResult<MessageEntity> msgList(Map<String, Object> map) {
		List<MessageEntity> msgList = new ArrayList<>();
		Map<String, TargetQueueInfo> queues = (Map<String, TargetQueueInfo>) map.get(MessageStr.QUEUE_LIST);
		for (Entry<String, TargetQueueInfo> entry : queues.entrySet()) {
			TargetQueueInfo queue = entry.getValue();
			String addr = entry.getKey();
			String messageId = map.get(MessageStr.MESSAGE_ID) != null ? this.toString() : null;
			Date startTime = map.get(MessageStr.START_TIME) == null ? null : (Date) map.get(MessageStr.START_TIME);
			Date endTime = map.get(MessageStr.END_TIME) == null ? null : (Date) map.get(MessageStr.END_TIME);
			Short status = map.get(MessageStr.STATUS) == null ? null : (Short) map.get(MessageStr.STATUS);

			List<MessageEntity> messageList = messageBrockerService.list(queue.getCode(), addr, messageId, startTime, endTime, status,
					null, 1, 50);
			if (messageList != null && !messageList.isEmpty()) {
				msgList.addAll(messageList);
			}
		}
		// 排序
		Collections.sort(msgList);
		return new PagedResult<MessageEntity>(msgList.size(), msgList, 1, 50);
	}

}
